package com.yanqu.road.server.manger.config;

import com.yanqu.road.entity.config.parergon.DiscountShopConfig;
import com.yanqu.road.entity.config.parergon.UnionParergonConfig;
import com.yanqu.road.entity.enums.eChannelType;
import com.yanqu.road.entity.union.trade.UnionTradeEventInfo;
import com.yanqu.road.entity.union.trade.UnionTradeRouteInfo;
import com.yanqu.road.logic.bussiness.config.ParergonConfigBussiness;
import com.yanqu.road.logic.bussiness.config.UnionConfigBussiness;
import com.yanqu.road.logic.bussiness.union.UnionTradeBussiness;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.enums.eUnionPosition;
import com.yanqu.road.entity.union.*;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.helper.PlatformHttpHelper;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.NameMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.union.UnionMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.math.MathUtil;
import com.yanqu.road.utils.string.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UnionConfigMgr extends TempMgr {

    private static final int MAX_UNION_WECHAT_LENGTH = 30;
    private static final int MAX_UNION_NOTICE_LENGTH = 200;

    private static List<UnionUpgradeInfo> unionUpgradeInfoList;

    private static Map<Integer, UnionConstructConfig> unionConstructConfigMap;

    private List<Integer> unionFlag;

    private static Map<Integer, DiscountShopConfig> discountShopConfigMap;
    private static List<DiscountShopConfig> discountShopConfigList;
    private static Map<Integer, Map<Integer, UnionParergonConfig>> parergonConfigByTypeAndQuality;
    private static Map<Integer, UnionParergonConfig> parergonConfigById;
    private static RandomHelper randomHelper = new RandomHelper();

    //routeId
    private static Map<Integer, UnionTradeRouteInfo> unionTradeRouteInfoMap;                 //路线信息
    //eventId
    private static Map<Integer, UnionTradeEventInfo>  unionTradeEventInfoMap;                //事件信息


    private static Pattern weChatPatten = Pattern.compile("^[A-Za-z0-9\\-_]+$");

    @Override
    public boolean reloadConfig() {
        unionUpgradeInfoList = UnionConfigBussiness.getUnionUpgradeInfoList();
        unionConstructConfigMap = UnionConfigBussiness.getUnionConstructConfigMap();

        discountShopConfigMap = ParergonConfigBussiness.getDiscountShopConfig();
        discountShopConfigList = new ArrayList<>(discountShopConfigMap.values());
        Map<Integer, Map<Integer, UnionParergonConfig>> tempParergonConfigByTypeAndQuality = new HashMap<>();
        Map<Integer, UnionParergonConfig> tempParergonConfigById = new HashMap<>();
        ParergonConfigBussiness.getUnionParergonConfig(tempParergonConfigByTypeAndQuality, tempParergonConfigById);
        parergonConfigByTypeAndQuality = tempParergonConfigByTypeAndQuality;
        parergonConfigById = tempParergonConfigById;

        unionTradeRouteInfoMap = UnionTradeBussiness.getUnionTradeRouteInfoMap();
        unionTradeEventInfoMap = UnionTradeBussiness.getUnionTradeEventInfoMap();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static UnionUpgradeInfo getUnionUpgradeInfo(long exp){
        for (int i = 0; i < unionUpgradeInfoList.size(); i++) {
            if (i == unionUpgradeInfoList.size() - 1) {
                return unionUpgradeInfoList.get(i);
            }
            if (unionUpgradeInfoList.get(i).getExperience() > exp) {
                return unionUpgradeInfoList.get(i);
            }
        }
        return null;
    }

    public static UnionConstructConfig getUnionConstructConfig(int type){
        return unionConstructConfigMap.get(type);
    }

    public static int getMaxMemberCount(long exp){
        UnionUpgradeInfo unionUpgradeInfo = getUnionUpgradeInfo(exp);
        if(null != unionUpgradeInfo){
            return unionUpgradeInfo.getMaxMemberCount();
        }
        return 0;
    }

    public static int getMaxMemberCount(long exp, boolean isCross, int crossServerCount){
        UnionUpgradeInfo unionUpgradeInfo = getUnionUpgradeInfo(exp);
        if(null != unionUpgradeInfo){
            if(isCross){
                return unionUpgradeInfo.getNewMaxPerson(crossServerCount);
            }
            return unionUpgradeInfo.getMaxMemberCount();
        }
        return 0;
    }

    public static int getUnionLv(long exp){
        UnionUpgradeInfo unionUpgradeInfo = getUnionUpgradeInfo(exp);
        if(null != unionUpgradeInfo){
            return unionUpgradeInfo.getLevel();
        }
        return 0;
    }

    public static boolean isContributionEnough(long contribution, int position) {
        return ConfigMgr.isContributionEnough(contribution, position);
    }

    public static boolean isPositionCountMax(UnionInfo unionInfo, Map<Long, UnionMember> memberMap, int position) {
        UnionUpgradeInfo unionUpgradeInfo = UnionConfigMgr.getUnionUpgradeInfo(unionInfo.getExperience());
        int count = getCountByPosition(memberMap, position);
        if (position == eUnionPosition.DeputyMaster.getValue()) {
            return count >= unionUpgradeInfo.getDeputyMasterCount();
        } else if (position == eUnionPosition.Elite.getValue()) {
            return count >= unionUpgradeInfo.getCreamCount();
        }
        return false;
    }

    public static int getCountByPosition(Map<Long, UnionMember> memberMap, int position) {
        int count = 0;
        if(null != memberMap) {
            for (UnionMember unionMember : memberMap.values()) {
                if (unionMember.getPosition() == position) {
                    count++;
                }
            }
        }
        return count;
    }

    public static long getLoseContribution(long contribution){
        double value = contribution;
        value = value * (1000 - GameConfig.UNION_QUIT_CONTRIBUTION_LOSE_PARAM) / 1000;
        return (long) value;
    }

    public static int checkUnionName(String unionName, String unionUid, GamePlayer player){
        int length = StringUtils.getStringLen(unionName);
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());

        if (eChannelType.isMainLandChannel(channelId)) {
            if (unionName.contains("🇨🇳")) {
                return GameErrorCode.E_FORBIDDEN_WORD;
            }
        }

        if(length > NameMgr.getMaxNickNameLength(channelId) || length < NameMgr.MIN_NICK_NAME_LENGTH){
            return GameErrorCode.E_UNION_NAME_LENGTH_OVER;
        }
        if (ForbiddenWordMgr.isUnionNameForbidden(unionName)) {
            return GameErrorCode.E_UNION_NAME_FORBIDDEN;
        }
        if(eChannelType.isMainLandChannel(channelId) && ChannelConfig.CN_FORBIDDEN_WORD_CHECK == 1){//大陆渠道，通过接口检测敏感词
            long curTime = System.currentTimeMillis();
            String appExt = "";
            if (player.getAppExt().containsKey("app_ext")) {
                appExt = player.getAppExt().getString("app_ext");
            }
            boolean isForbidden = PlatformHttpHelper.platformCheckUnion(GameServer.getInstance().getServerId(), unionUid,
                    PlatformHttpHelper.UnionNameType, unionName, player.getAppId(), appExt);
            getLogger().info("platformCheckUnion use:{}ms", System.currentTimeMillis() - curTime);
            if(isForbidden){
                return GameErrorCode.E_UNION_NAME_FORBIDDEN;
            }
        }
        return 0;
    }

    public static int checkWechatCode(String wechatCode){
        int length = StringUtils.getStringLen(wechatCode);
        if(length > UnionConfigMgr.MAX_UNION_WECHAT_LENGTH){
            return GameErrorCode.E_UNION_WECHAT_LENGTH_OVER;
        }

        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        if (eChannelType.isMainLandChannel(channelId) || channelId == eChannelType.MainLandInnerTest.getValue()) {
            //大陆渠道 要验证联系方式只允许为数字 字母 横杠 下划线
            Matcher matcher = weChatPatten.matcher(wechatCode);
            if (!matcher.matches()) {
                return GameErrorCode.E_UNION_WECHAT_FORBIDDEN;
            }else {
                return 0;
            }
        }

        if(ForbiddenWordMgr.isUnionForbidden(wechatCode)){
            return GameErrorCode.E_UNION_WECHAT_FORBIDDEN;
        }
        return 0;
    }

    public static int checkQqCode(String qqCode){
        if (ForbiddenWordMgr.isQQForbidden(qqCode)) {
            return GameErrorCode.E_UNION_QQ_FORBIDDEN;
        }
        return 0;
    }

    public static int checkOutNotice(String outNotice, String unionUid, GamePlayer player){
        int length = StringUtils.getStringLen(outNotice);
        if(length > UnionConfigMgr.MAX_UNION_NOTICE_LENGTH){
            return GameErrorCode.E_UNION_OUT_NOTICE_LENGTH_OVER;
        }
        if (ForbiddenWordMgr.isUnionForbidden(outNotice)) {
            return GameErrorCode.E_UNION_OUT_NOTICE_FORBIDDEN;
        }
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        if(eChannelType.isMainLandChannel(channelId) && ChannelConfig.CN_FORBIDDEN_WORD_CHECK == 1){//大陆渠道，通过接口检测敏感词
            long curTime = System.currentTimeMillis();
            String appExt = "";
            if (player.getAppExt().containsKey("app_ext")) {
                appExt = player.getAppExt().getString("app_ext");
            }
            boolean isForbidden = PlatformHttpHelper.platformCheckUnion(GameServer.getInstance().getServerId(), unionUid,
                    PlatformHttpHelper.UnionNoticeType, outNotice, player.getAppId(), appExt);
            getLogger().info("platformCheckUnion use:{}ms", System.currentTimeMillis() - curTime);
            if(isForbidden){
                return GameErrorCode.E_UNION_OUT_NOTICE_FORBIDDEN;
            }
        }
        return 0;
    }

    public static int checkInnerNotice(String innerNotice){
        int length = StringUtils.getStringLen(innerNotice);
        if(length > UnionConfigMgr.MAX_UNION_NOTICE_LENGTH){
            return GameErrorCode.E_UNION_INNER_NOTICE_LENGTH_OVER;
        }
        if (ForbiddenWordMgr.isUnionForbidden(innerNotice)) {
            return GameErrorCode.E_UNION_INNER_NOTICE_FORBIDDEN;
        }
        return 0;
    }

    public static int getUnionChamberOccupationPatronsCount(int occupation, String unionUid, long userId){
        int count = 0;
        Map<Long, UnionMember> memberMap = UnionMgr.getUnionMemberMap(unionUid);
        if(null != memberMap) {
            for(UnionMember unionMember : memberMap.values()) {
                if(unionMember.getUserId() == userId){
                    continue;
                }
                PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(unionMember.getChamberPatronsId());
                if (null != patronsInfo && patronsInfo.getOccupation() == occupation) {
                    count++;
                }
            }
        }
        return count;
    }

    public static UnionParergonConfig getParergonConfig(int parergonId) {
        return parergonConfigById.get(parergonId);
    }
    public static DiscountShopConfig getDiscountShopConfig(int productId) {
        return discountShopConfigMap.get(productId);
    }

    public static Map<Integer, DiscountShopConfig> getDiscountShopConfigMap() {
        return discountShopConfigMap;
    }
    public static Map<Integer, Map<Integer, UnionParergonConfig>> getUnionParergonConfigByTypeAndQuality() {
        return parergonConfigByTypeAndQuality;
    }
    public static Map<Integer, UnionParergonConfig> getParergonConfigById() {
        return  parergonConfigById;
    }

    /**
     * 初始化行脚商人的砍价值（首个商人特殊处理）
     * @param barginNum      砍价上限人数
     * @param shopConfig     折扣商店配置
     * @param parergonTimes  总的商人出现次数
     * @return
     */
    public static List<Integer> initBargainList(int barginNum, DiscountShopConfig shopConfig, int parergonTimes) {
        List<Integer> dataList = new ArrayList<>();
        List<Integer> paramList = shopConfig.getParamList();
        int param1 = paramList.get(0);
        if(1 == parergonTimes){
            param1 = 1000;
        }
        int param2 = paramList.get(1);
        int param3 = paramList.get(2);
        int param4 = (int) Math.floor((double)paramList.get(3) / barginNum);
        double q,k,qt;
        double y = (double) randomHelper.next(param1, param2) * shopConfig.getPrice() / 1000;
        for (int i = 1; i < barginNum; i++) {
            double x = ((double)1000 / (barginNum - i + 1) - param4) / (param3 - param4);
            qt = MathUtil.customLog(0.5, x);
            q = Math.max(0.01, qt);
            double r1 = randomHelper.nextDouble(0, 1);
            k = (MathUtil.customPow(r1, q, 3) * (param3 - param4) + param4) * y / 1000;
            y = y - k;
            dataList.add((int) k);
        }
        k = y;
        dataList.add((int) k);
        return dataList;
    }

    /**
     * 随机获取一个折扣商店配置
     */
    public static DiscountShopConfig getRandomDiscountShopConfig(){
        int randomIndex = randomHelper.next(0, discountShopConfigList.size());
        return discountShopConfigList.get(randomIndex);
    }

    /**
     * 是否出现行脚商人
     * @param parergonConfig
     * @return
     */
    public static boolean hasShowUnionParergon(UnionParergonConfig parergonConfig){
        int value = randomHelper.next(0, 1000);
        return value < parergonConfig.getDiscountShopPro();
    }

    /**
     * 随机一个副业
     * @param lastParergonId  上次副业编号
     * @param unionUid
     * @return
     */
    public static UnionParergonConfig getRandomUnionParergonConfig(int lastParergonId, String unionUid){
        //先随机一个类型
        Integer type = (Integer) randomHelper.randomList(parergonConfigByTypeAndQuality.keySet());
        //再随机一个品质
        UnionInfo unionInfo = UnionMgr.getUnionInfo(unionUid);
        UnionUpgradeInfo unionUpgradeInfo = UnionConfigMgr.getUnionUpgradeInfo(unionInfo.getExperience());

        int qualityValue = randomHelper.next(unionUpgradeInfo.getWeight());
        int index = unionUpgradeInfo.getIndexByWeight(qualityValue);
        UnionParergonConfig parergonConfig = parergonConfigByTypeAndQuality.get(type).get(index + 1);
        int count = 0;
        while (parergonConfig.getId() == lastParergonId) {
            qualityValue = randomHelper.next(unionUpgradeInfo.getWeight());
            index = unionUpgradeInfo.getIndexByWeight(qualityValue);
            parergonConfig = parergonConfigByTypeAndQuality.get(type).get(index + 1);
            if (count++ == 10) {
                break;
            }
        }
        return parergonConfig;
    }


    //事件配置
    public static UnionTradeEventInfo getUnionTradeEventInfo(int eventId) {
        return unionTradeEventInfoMap.get(eventId);
    }
    //路线配置
    public static UnionTradeRouteInfo getUnionTradeRouteInfo(int routeId){
        return unionTradeRouteInfoMap.get(routeId);
    }
    //路线配置
    public static Map<Integer, UnionTradeRouteInfo> getUnionTradeRouteInfoMap() {
        return unionTradeRouteInfoMap;
    }

    public static int getMinApplyTitle() {
        try {
            String[] arr = GameConfig.UNION_JOIN_APPLY_NEED_TITLE.split(",");
            return Integer.parseInt(arr[0]);
        } catch (Exception e) {
            getLogger().error("union apply title error. {}", GameConfig.UNION_JOIN_APPLY_NEED_TITLE);
        }
        return 9;
    }

    public static int getMaxApplyTitle() {
        try {
            String[] arr = GameConfig.UNION_JOIN_APPLY_NEED_TITLE.split(",");
            return Integer.parseInt(arr[1]);
        } catch (Exception e) {
            getLogger().error("union apply title error. {}", GameConfig.UNION_JOIN_APPLY_NEED_TITLE);
        }
        return 9;
    }

}
